package com.lej.dataservice.club.http

import androidx.lifecycle.*
import com.lej.core.utils.extention.safe
import com.lej.dataservice.club.http.bean.ResStatus
import kotlinx.coroutines.launch

inline fun <T> LifecycleOwner.ownerRequest(
    crossinline block: suspend () -> BaseResponse<T>,
    crossinline success: suspend (T) -> Unit,
    crossinline fail: suspend (Int, String?) -> Unit = { _, _ -> },
) {
    lifecycleScope.launch {
        runCatching {
            val res = block()
            success(res.checkData())
        }.onFailure { fail.invoke(it.handleCode, it.handleMsg) }
    }
}

inline fun <T> ViewModel.request(
    crossinline block: suspend () -> BaseResponse<T>,
    crossinline fail: suspend (Throwable) -> Unit = {},
    crossinline success: suspend (T) -> Unit,
) {
    viewModelScope.launch {
        runCatching {
            val res = block()
            success(res.checkData())
        }.onFailure {
            fail(it)
        }
    }
}

fun <TR> mapLive() = MutableLiveData<ResStatus<TR>>()

inline fun <reified T> ViewModel.request(
    liveData: MutableLiveData<ResStatus<T>>? = null,
    crossinline block: suspend () -> BaseResponse<T>,
): MutableLiveData<ResStatus<T>> {
    val resData: MutableLiveData<ResStatus<T>> = liveData ?: mapLive()
    viewModelScope.launch {
        resData.postValue(ResStatus.Loading())
        runCatching { resData.postValue(ResStatus.Success(block().checkData())) }
            .onFailure { resData.postValue(ResStatus.Error(it)) }
    }
    return resData
}

inline fun <reified T> ViewModel.requestList(
    liveData: MutableLiveData<ResStatus<List<T>>>? = null,
    crossinline block: suspend () -> BaseListRes<T>,
): MutableLiveData<ResStatus<List<T>>> {
    val resData: MutableLiveData<ResStatus<List<T>>> = liveData ?: mapLive()
    viewModelScope.launch {
        resData.postValue(ResStatus.Loading())
        runCatching { resData.postValue(ResStatus.Success(block().checkList().safe())) }
            .onFailure { resData.postValue(ResStatus.Error(it)) }
    }
    return resData
}


inline fun <reified T, TR> ViewModel.requestMap(
    liveData: MutableLiveData<ResStatus<T>>? = null,
    crossinline map: suspend TR.() -> T,
    crossinline block: suspend () -> BaseResponse<TR>,
): MutableLiveData<ResStatus<T>> {
        val resData: MutableLiveData<ResStatus<T>> = liveData ?: mapLive()
    viewModelScope.launch {
        resData.postValue(ResStatus.Loading())
        runCatching { resData.postValue(ResStatus.Success(block().checkData().map())) }
            .onFailure { resData.postValue(ResStatus.Error(it)) }
    }
    return resData
}